package top.chmin.project.cloud.sys.code;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import top.chmin.project.cloud.common.*;
import top.chmin.project.cloud.tool.LocalTool;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;



/**
 * chmin
 * 2024-01-26 14:00:51
 * cloud-code
 */
@Getter
@Setter
@Accessors(chain = true)
public class Code extends Model {
    /*###########auto#start###########*/
    // column编号
    private String columnCode;
    // 编码日期
    private String date;
    // 补齐长度
    private Integer fixLength;
    // 初始值
    private Integer nextValue;
    // 表前缀
    private String prefix;
    /*###########auto##end############*/
    /* append $modelFieldAppender$ */

    public CodeModelCondition forInsert() {
        return new CodeModelCondition().forInsert();
    }

    public CodeModelCondition forUpdate() {
        return new CodeModelCondition().forUpdate();
    }

    public CodeModelCondition forDelete() {
        return new CodeModelCondition().forDelete();
    }

    public CodeModelCondition forSelect() {
        return new CodeModelCondition().forSelect();
    }

    public class CodeModelCondition extends Condition {
        CodeModelCondition parent = null;

        private CodeModelCondition() {
        }

        private CodeModelCondition(CodeModelCondition condition) {
            this.parent = condition;
        }

        private CodeModelCondition forInsert() {
            CodeModelCondition condition = new CodeModelCondition();
            List<String> columnNameList = new ArrayList<>();
            List<String> valueList = new ArrayList<>();
            /*###########auto#start###########*/
            columnNameList.add("column_code");
            valueList.add("?");
            condition.getValueList().add(getColumnCode());

            columnNameList.add("date");
            valueList.add("?");
            condition.getValueList().add(getDate());

            columnNameList.add("fix_length");
            valueList.add("?");
            condition.getValueList().add(getFixLength());

            columnNameList.add("next_value");
            valueList.add("?");
            condition.getValueList().add(getNextValue());

            columnNameList.add("prefix");
            valueList.add("?");
            condition.getValueList().add(getPrefix());

            /*###########auto##end############*/
            /* append $modelForInsertFieldAppender$ */
            condition.getValueList().add(LocalTool.getUserId());
            condition.getValueList().add(LocalTool.getUserId());
            condition.getValueList().add(LocalDateTime.now());
            condition.getValueList().add(LocalDateTime.now());
            condition.setSql("INSERT INTO sys_code(%s, create_by, update_by, create_time, update_time) VALUES (%s, ?, ?, ?, ?)".formatted(
                    String.join(", ", columnNameList),
                    String.join(", ", valueList)
            ));
            return condition;
        }

        private CodeModelCondition forUpdate() {
            CodeModelCondition condition = new CodeModelCondition();
            /*###########auto#start###########*/
            if (columnCode != null) {
                condition.getUpdateList().add("column_code = ?");
                condition.getUpdateValueList().add(columnCode);
            }

            if (date != null) {
                condition.getUpdateList().add("date = ?");
                condition.getUpdateValueList().add(date);
            }

            if (fixLength != null) {
                condition.getUpdateList().add("fix_length = ?");
                condition.getUpdateValueList().add(fixLength);
            }

            if (nextValue != null) {
                condition.getUpdateList().add("next_value = ?");
                condition.getUpdateValueList().add(nextValue);
            }

            if (prefix != null) {
                condition.getUpdateList().add("prefix = ?");
                condition.getUpdateValueList().add(prefix);
            }

            /*###########auto##end############*/
            /* append $modelForUpdateFieldAppender$ */
            if (getUpdateBy() != null) {
                condition.getUpdateList().add("update_by = ?");
                condition.getUpdateValueList().add(getUpdateBy());
            }
            if (getUpdateTime() != null) {
                condition.getUpdateList().add("update_time = ?");
                condition.getUpdateValueList().add(getUpdateTime());
            }
            condition.setSql("UPDATE sys_code#update##where##order##limit#");
            return condition;
        }

        private CodeModelCondition forDelete() {
            CodeModelCondition condition = new CodeModelCondition();
            condition.setSql("DELETE FROM sys_code#where##group##order##limit#");
            return condition;
        }

        private CodeModelCondition forSelect() {
            CodeModelCondition condition = new CodeModelCondition();
            condition.modelClass = Code.class;
            condition.setSql("SELECT #select# FROM sys_code#where##group##order##limit#");
            return condition;
        }

        public CodeModelCondition distinct() {
            this.distinct = true;
            return this;
        }

        public CodeModelCondition limit(int limit) {
            this.limit = " LIMIT " + limit;
            return this;
        }

        public CodeModelCondition sub() {
            return new CodeModelCondition(this);
        }

        public CodeModelCondition finish() {
            if (!whereList.isEmpty()) {
                parent.whereList.add("(" + String.join(" OR ", whereList) + ")");
            }
            parent.whereValueList.addAll(whereValueList);
            return parent;
        }

        public CodeCondition toFlex() {
            CodeCondition flex = new CodeCondition();
            flex.setSql(sql);
            flex.setDistinct(distinct);
            flex.setModelClass(modelClass);
            flex.setSelectList(selectList);
            flex.setUpdateList(updateList);
            flex.setUpdateValueList(updateValueList);
            flex.setWhereList(whereList);
            flex.setWhereValueList(whereValueList);
            flex.setGroupList(groupList);
            flex.setOrderList(orderList);
            flex.setLimit(limit);
            return flex;
        }

        /*###########auto#start###########*/
        public ColumnCode columnCode() {
            return new ColumnCode();
        }

        public class ColumnCode extends StringModelColumn<CodeModelCondition> {
            private ColumnCode() {
                super(CodeModelCondition.this, "column_code", Code.this.getColumnCode());
            }
        }

        public CreateBy createBy() {
            return new CreateBy();
        }

        public class CreateBy extends StringModelColumn<CodeModelCondition> {
            private CreateBy() {
                super(CodeModelCondition.this, "create_by", Code.this.getCreateBy());
            }
        }

        public CreateTime createTime() {
            return new CreateTime();
        }

        public class CreateTime extends LocalDateTimeModelColumn<CodeModelCondition> {
            private CreateTime() {
                super(CodeModelCondition.this, "create_time", Code.this.getCreateTime());
            }
        }

        public Date date() {
            return new Date();
        }

        public class Date extends StringModelColumn<CodeModelCondition> {
            private Date() {
                super(CodeModelCondition.this, "date", Code.this.getDate());
            }
        }

        public FixLength fixLength() {
            return new FixLength();
        }

        public class FixLength extends IntegerModelColumn<CodeModelCondition> {
            private FixLength() {
                super(CodeModelCondition.this, "fix_length", Code.this.getFixLength());
            }
        }

        public Id id() {
            return new Id();
        }

        public class Id extends IntegerModelColumn<CodeModelCondition> {
            private Id() {
                super(CodeModelCondition.this, "id", Code.this.getId());
            }
        }

        public NextValue nextValue() {
            return new NextValue();
        }

        public class NextValue extends IntegerModelColumn<CodeModelCondition> {
            private NextValue() {
                super(CodeModelCondition.this, "next_value", Code.this.getNextValue());
            }
        }

        public Prefix prefix() {
            return new Prefix();
        }

        public class Prefix extends StringModelColumn<CodeModelCondition> {
            private Prefix() {
                super(CodeModelCondition.this, "prefix", Code.this.getPrefix());
            }
        }

        public UpdateBy updateBy() {
            return new UpdateBy();
        }

        public class UpdateBy extends StringModelColumn<CodeModelCondition> {
            private UpdateBy() {
                super(CodeModelCondition.this, "update_by", Code.this.getUpdateBy());
            }
        }

        public UpdateTime updateTime() {
            return new UpdateTime();
        }

        public class UpdateTime extends LocalDateTimeModelColumn<CodeModelCondition> {
            private UpdateTime() {
                super(CodeModelCondition.this, "update_time", Code.this.getUpdateTime());
            }
        }

        /*###########auto##end############*/
        /* append $modelConditionFieldAppender$ */
    }
}
